package io.gitee.chearnee.fw.dingtalk.util;

import io.gitee.chearnee.fw.dingtalk.property.DingTalkProperties;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author cn
 * @version 1.0
 * @description
 * @date 2021/7/27 20:02
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DingTalkUtil {

  private final DingTalkProperties dingTalkProperties;

  public DingTalkProperties.DingTalkConfig getProperty(String name) {
    Set<DingTalkProperties.DingTalkConfig> configs = dingTalkProperties.getConfigs();
    if (CollectionUtils.isEmpty(configs)) {
      throw new RuntimeException("configs must not be null");
    }
    Map<String, DingTalkProperties.DingTalkConfig> configMap = configs.stream()
            .collect(Collectors.toMap(DingTalkProperties.DingTalkConfig::getName, Function.identity()));
    if (!StringUtils.hasText(name)) {
      name = "default";
    }
    DingTalkProperties.DingTalkConfig dingTalkConfig = configMap.get(name);
    if (dingTalkConfig == null) {
      throw new RuntimeException("not found this name's config");
    }
    return dingTalkConfig;
  }

  @SneakyThrows
  private String sign(Long timestamp, String name) {
    String stringToSign = timestamp + "\n" + getProperty(name).getSecret();
    Mac mac = Mac.getInstance("HmacSHA256");
    mac.init(new SecretKeySpec(getProperty(name).getSecret().getBytes(StandardCharsets.UTF_8),
        "HmacSHA256"));
    byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
    return URLEncoder
            .encode(new String(Base64.getEncoder().encode(signData), StandardCharsets.UTF_8),
                    StandardCharsets.UTF_8);
  }

  public String buildRequestUrl(String uri, String accessToken, String name) {
    StringBuilder stringBuffer = new StringBuilder(dingTalkProperties.getBaseServerUrl());
    stringBuffer.append(uri).append("?").append("access_token=");
    if (StringUtils.hasText(accessToken)) {
      stringBuffer.append(accessToken);
    } else {
      stringBuffer.append(getProperty(name).getAccessToken());
    }
    Long timestamp = System.currentTimeMillis();
    stringBuffer.append("&timestamp=").append(timestamp).append("&sign=")
        .append(sign(timestamp, name));
    return stringBuffer.toString();
  }
}
